/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package GUIUtilities;

import java.util.HashMap;
import java.util.Vector;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultMutableTreeNode;

/**
 *
 * @author Heather
 */
public abstract class TreeUtilities
{

  // clones up to and inclurding the desired depth.  root = depth 1
  public static void cloneTree(JTree source, JTree target, int depth)
  {
    int currentDepth = 1;
    DefaultMutableTreeNode sourceRoot = (DefaultMutableTreeNode) source.getModel().getRoot();
    DefaultMutableTreeNode targetRoot = (DefaultMutableTreeNode) target.getModel().getRoot();
    targetRoot.removeAllChildren();

    Vector<DefaultMutableTreeNode> queue = new Vector<DefaultMutableTreeNode>();
    for (int i = 0; i < sourceRoot.getChildCount(); i++)
    {
      queue.add((DefaultMutableTreeNode) sourceRoot.getChildAt(i));
    }

    DefaultMutableTreeNode parent;
    HashMap<DefaultMutableTreeNode, DefaultMutableTreeNode> sourceToTargetMap = new HashMap<DefaultMutableTreeNode, DefaultMutableTreeNode>();
    sourceToTargetMap.put(sourceRoot, targetRoot);
    while ((queue.size() > 0) && (currentDepth <= depth))
    {
      // pop
      DefaultMutableTreeNode popped = queue.get(0);
      queue.remove(popped);
      currentDepth = getDepth(popped);

      System.out.println(popped.getUserObject());

      if (currentDepth <= depth)
      {
        DefaultMutableTreeNode newNode = new DefaultMutableTreeNode((String) popped.getUserObject());
        sourceToTargetMap.put(popped, newNode);
        parent = sourceToTargetMap.get((DefaultMutableTreeNode) popped.getParent());
        parent.add(newNode);

        // enqueue all popped children
        for (int i = 0; i < popped.getChildCount(); i++)
        {
          queue.add((DefaultMutableTreeNode) popped.getChildAt(i));
        }
      }
    }

    target.updateUI();
  }

  // clones up to and inclurding the desired depth.  root = depth 1
  public static void cloneTree(JTree source, JTree target, boolean isCloningLeaves)
  {
    DefaultMutableTreeNode sourceRoot = (DefaultMutableTreeNode) source.getModel().getRoot();
    DefaultMutableTreeNode targetRoot = (DefaultMutableTreeNode) target.getModel().getRoot();
    targetRoot.removeAllChildren();

    Vector<DefaultMutableTreeNode> queue = new Vector<DefaultMutableTreeNode>();
    for (int i = 0; i < sourceRoot.getChildCount(); i++)
    {
      queue.add((DefaultMutableTreeNode) sourceRoot.getChildAt(i));
    }

    DefaultMutableTreeNode parent;
    HashMap<DefaultMutableTreeNode, DefaultMutableTreeNode> sourceToTargetMap = new HashMap<DefaultMutableTreeNode, DefaultMutableTreeNode>();
    sourceToTargetMap.put(sourceRoot, targetRoot);
    while (queue.size() > 0)
    {
      // pop
      DefaultMutableTreeNode popped = queue.get(0);
      queue.remove(popped);

      System.out.println(popped.getUserObject());

      DefaultMutableTreeNode newNode = new DefaultMutableTreeNode((String) popped.getUserObject());
      sourceToTargetMap.put(popped, newNode);

      if (!popped.isLeaf() || (popped.isLeaf() && isCloningLeaves))
      {
        parent = sourceToTargetMap.get((DefaultMutableTreeNode) popped.getParent());
        parent.add(newNode);
      }

      // enqueue all popped children
      for (int i = 0; i < popped.getChildCount(); i++)
      {
        queue.add((DefaultMutableTreeNode) popped.getChildAt(i));
      }
    }

    target.updateUI();
  }

  private static int getDepth(DefaultMutableTreeNode node)
  {
    int ret = 1;

    DefaultMutableTreeNode current = node;
    DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();
    while (parent != null)
    {
      current = parent;
      parent = (DefaultMutableTreeNode) current.getParent();
      ret++;
    }

    return ret;
  }

  public static DefaultMutableTreeNode findAscriptiveCategory(JTree searchTree, String member)
  {
    DefaultMutableTreeNode root = (DefaultMutableTreeNode) searchTree.getModel().getRoot();
    Vector<DefaultMutableTreeNode> queue = new Vector<DefaultMutableTreeNode>();
    for (int i = 0; i < root.getChildCount(); i++)
    {
      queue.add((DefaultMutableTreeNode) root.getChildAt(i));
    }

    while (queue.size() > 0)
    {
      DefaultMutableTreeNode popped = queue.get(0);
      queue.remove(popped);

      if (popped.getUserObject().equals(member))
      {
        return getTopParent(popped);
      }

      // queue children
      for (int i = 0; i < popped.getChildCount(); i++)
      {
        queue.add((DefaultMutableTreeNode) popped.getChildAt(i));
      }
    }

    return null;
  }

  private static DefaultMutableTreeNode getTopParent(DefaultMutableTreeNode node)
  {
    DefaultMutableTreeNode current = node;
    DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();

    while (parent != null)
    {
      current = parent;
      parent = (DefaultMutableTreeNode) current.getParent();
    }

    return current;
  }

  public static int getSelectedAscriptiveCategoryIndex(JTree ascriptiveTree)
  {
    int ret = -1;

    DefaultMutableTreeNode root = (DefaultMutableTreeNode) ascriptiveTree.getModel().getRoot();
    DefaultMutableTreeNode selected = (DefaultMutableTreeNode)ascriptiveTree.getLastSelectedPathComponent();

    for (int i = 0; i < root.getChildCount(); i++)
    {
      Vector<DefaultMutableTreeNode> queue = new Vector<DefaultMutableTreeNode>();
      queue.add((DefaultMutableTreeNode)root.getChildAt(i));

      // use bfs to see if node exists in this child's row
      while(queue.size() > 0)
      {
        DefaultMutableTreeNode popped = queue.get(0);
        queue.remove(popped);

        if (popped.equals(selected))
        {
          return i;
        }
        // enqueue children
        else
        {
          for (int j = 0; j < popped.getChildCount(); j++)
          {
            queue.add((DefaultMutableTreeNode)popped.getChildAt(j));
          }
        }
      }

    }

    return ret;
  }

  // returns the first node with the user object name
  public static DefaultMutableTreeNode getAscriptiveNode(String name, JTree ascriptiveTree)
  {
    DefaultMutableTreeNode root = (DefaultMutableTreeNode) ascriptiveTree.getModel().getRoot();
    Vector<DefaultMutableTreeNode> queue = new Vector<DefaultMutableTreeNode>();
    for(int i = 0; i < root.getChildCount(); i++)
    {
      queue.add((DefaultMutableTreeNode)root.getChildAt(i));
    }

    while(queue.size() > 0)
    {
      DefaultMutableTreeNode popped = queue.get(0);
      queue.remove(popped);

      String poppedName = (String)popped.getUserObject();
      if (poppedName.equals(name))
        return popped;
      else
      {
        for (int j = 0; j < popped.getChildCount(); j++)
        {
          queue.add((DefaultMutableTreeNode)popped.getChildAt(j));
        }
      }
    }

    return null;
  }


  // returns the category index of given string.  If there are 2 same strings, then it
  // returns the first??
          /*
  public static int getAscriptiveCategoryIndex(String s, JTree ascriptiveTree)
  {
    int ret = -1;

    DefaultMutableTreeNode root = (DefaultMutableTreeNode) ascriptiveTree.getModel().getRoot();

    Vector<Vector<DefaultMutableTreeNode>> allQueues = new Vector<Vector<DefaultMutableTreeNode>>();
    for (int i = 0; i < root.getChildCount(); i++)
    {
      Vector<DefaultMutableTreeNode> aQueue = new Vector<DefaultMutableTreeNode>();
      aQueue.add((DefaultMutableTreeNode)root.getChildAt(i));
      allQueues.add(aQueue);
    }

    

    return ret;
  }*/
}
